use std::collections::HashMap;

use actix_web::{delete, error, get, post, put, web, Error, HttpRequest, HttpResponse};
use datasource_connector::restful::{
    get_class, get_instance_by_id, get_instances, instance_delete, post_instance, put_instance,
};
use model_graph_types::{
    datasource::{
        AttributeConditionBuilder, DataSourceProvider, DeleteCondition, DeleteConditionBuilder,
        GetDataSourceOptions, QueryCondition, QueryExtention, QueryOptions, UpdateCondition,
    },
    modeling::{system_meta_database, ComparsionOperator},
};
use serde::{Deserialize, Serialize};
use serde_json::json;

#[get("/ds/rest/{clazz}/{id}")]
pub async fn ds_restful_get_by_id(
    state: web::Data<crate::AppState>,
    identifier_param: web::Path<(String, String)>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();
    //用户ID
    // let user_id = crate::services::get_user_id(&req)?;

    let (clazz, id) = identifier_param.into_inner();

    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;

    let res = get_instance_by_id(
        context,
        &Some(meta_datasource),
        &default_datasource,
        &clazz,
        &id,
    )
    .await
    .map_err(|err| error::ErrorInternalServerError(err))?;

    Ok(HttpResponse::Ok().json(json!(res)))
}

#[put("/ds/rest/{clazz}/{id}")]
pub async fn ds_restful_update(
    state: web::Data<crate::AppState>,
    identifier_param: web::Path<(String, String)>,
    values_json: web::Json<HashMap<String, serde_json::Value>>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();

    let (clazz, id) = identifier_param.into_inner();
    //用户ID
    // let user_id = crate::services::get_user_id(&req)?;
    //
    let values = values_json.into_inner();

    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;
    let res = put_instance(
        context,
        &Some(meta_datasource),
        &default_datasource,
        &clazz,
        UpdateCondition::default(),
        values,
        None,
    )
    .await
    .map_err(|err| error::ErrorInternalServerError(err))?;

    Ok(HttpResponse::Ok().json(json!(res)))
}

#[post("/ds/rest/{clazz}")]
pub async fn ds_restful_post(
    state: web::Data<crate::AppState>,
    identifier_param: web::Path<String>,
    values_json: web::Json<HashMap<String, serde_json::Value>>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();

    let clazz = identifier_param.into_inner();
    //用户ID
    //
    let values = values_json.into_inner();

    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;
    let res = post_instance(
        context,
        &Some(meta_datasource),
        &default_datasource,
        &clazz,
        values,
        None,
    )
    .await
    .map_err(|err| error::ErrorInternalServerError(err))?;

    Ok(HttpResponse::Ok().json(json!(res)))
}

#[delete("/ds/rest/{clazz}/{id}")]
pub async fn ds_restful_delete(
    state: web::Data<crate::AppState>,
    identifier_param: web::Path<(String, String)>,
    _req: HttpRequest,
) -> Result<HttpResponse, Error> {
    //
    let context = state.context.clone();

    let (clazz, id) = identifier_param.into_inner();
    //用户ID
    // let user_id = crate::services::get_user_id(&req)?;
    let meta_datasource =
        system_meta_database().map_err(|err| error::ErrorInternalServerError(err))?;
    let default_datasource = context
        .get_datasource(GetDataSourceOptions::default())
        .await
        .map_err(|err| error::ErrorInternalServerError(err))?;
    let res = instance_delete(
        context,
        &Some(meta_datasource),
        &default_datasource,
        &clazz,
        DeleteConditionBuilder::default()
            .attributes(vec![AttributeConditionBuilder::default()
                .name("identifier")
                .operator(ComparsionOperator::Equal)
                .value(id)
                .build()
                .map_err(|err| error::ErrorInternalServerError(err))?])
            .build()
            .map_err(|err| error::ErrorInternalServerError(err))?,
        None,
    )
    .await
    .map_err(|err| error::ErrorInternalServerError(err))?;

    Ok(HttpResponse::Ok().json(json!(res)))
}
